adduser — Create Linux Users Safely
By the end of this lesson, you will be able to create interactive and non-interactive accounts, choose safe defaults (home, shell, group), and verify new users before granting WordPress file access.
Overview
adduser is Ubuntu's high-level account creation tool. It wraps low-level user creation into a safer workflow by creating a user, initializing their home directory, and setting profile data with fewer manual steps.
Compared with useradd, adduser is easier to use correctly in multi-admin WordPress VPS environments where clean onboarding and predictable permissions matter.
- Core Function: Create local Linux users with standard Debian/Ubuntu defaults.
- Primary Benefit: Reduces onboarding mistakes and permission drift.
- Where to Use: Developer onboarding, deploy account setup, service-account provisioning.
- Workflow:
adduser [OPTIONS] USERNAME.
adduser is part of the Debian/Ubuntu user management toolchain and is typically used from SSH sessions or provisioning scripts.
System Check
Ensure adduser is available and check your version:
which adduser # Expected: /usr/sbin/adduser
adduser --version # Shows adduser package version
Syntax & Expression Rules
The command follows a logical structure that reads almost like a sentence:
adduser [OPTIONS] USERNAME [GROUP]
[OPTIONS]: Flags such as--disabled-password,--home, and--shell.USERNAME: The account name to create (for examplewpdev,deployer,backupbot).[GROUP]: Optional existing group when adding an existing user to an existing group.
Account Creation Flags
| Expression | Description | Example Syntax | ⭐ Rating |
|---|---|---|---|
| :-- | :-- | :-- | :-- |
--disabled-password | Create account without interactive password login | sudo adduser --disabled-password deployer | ⭐⭐⭐⭐⭐ |
--disabled-login | Disable shell login for account | sudo adduser --disabled-login backupbot | ⭐⭐⭐⭐⭐ |
--home DIR | Set custom home path | sudo adduser --home /srv/sites/site1 wpdev1 | ⭐⭐⭐⭐ |
--shell SHELL | Set login shell explicitly | sudo adduser --shell /bin/bash wpdev | ⭐⭐⭐⭐ |
--ingroup GROUP | Set primary group on creation | sudo adduser --ingroup www-data uploader | ⭐⭐⭐ |
--uid UID | Set specific UID | sudo adduser --uid 1205 stagingdev | ⭐⭐⭐ |
--system | Create low-privilege system account | sudo adduser --system wpcron | ⭐⭐⭐⭐ |
--gecos "TEXT" | Fill profile fields non-interactively | sudo adduser --gecos "WP Dev,,," --disabled-password wpdev | ⭐⭐⭐ |
Provisioning Actions
| Action | Description | WordPress/VPS Use Case | Example Syntax |
|---|---|---|---|
| :-- | :-- | :-- | :-- |
| Create human user | Interactive account with password prompt | Onboard a new maintainer | sudo adduser wpadmin |
| Create deploy user | Password-disabled account for SSH keys | CI/CD deploy account | sudo adduser --disabled-password deployer |
| Create service identity | System/non-login user | Backup, sync, or cron process | sudo adduser --system --group wpbackup |
| Grant web-write access | Add user to web group after creation | Allow theme/plugin edits in /var/www/html | sudo usermod -aG www-data wpdev |
Practical Use Cases
1. Create a standard developer account
sudo adduser wpdev
Expected output:
Adding user `wpdev' ...
Adding new group `wpdev' (1003) ...
Creating home directory `/home/wpdev' ...
Copying files from `/etc/skel' ...
passwd: password updated successfully
Explanation: Creates the user, primary group, and home directory. Use case: Day-one onboarding for a WordPress developer.
2. Create deploy user with SSH-key-only login
sudo adduser --disabled-password --gecos "Deploy Bot,,," deployer
Expected output:
Adding user `deployer' ...
Creating home directory `/home/deployer' ...
Adding new user `deployer' to supplemental / extra groups `users' ...
Explanation: Skips password prompt so you can enforce SSH keys. Use case: Deployment account for GitHub Actions or CI runners.
3. Create non-login backup service account
sudo adduser --disabled-login --system --group wpbackup
Expected output:
Adding system user `wpbackup' (UID 998) ...
Adding new group `wpbackup' (GID 998) ...
Not creating home directory `/home/wpbackup'.
Explanation: Creates a service identity that cannot start a shell session. Use case: Scheduled backup jobs with minimal attack surface.
4. Create account with custom project home
sudo adduser --home /srv/clients/site1/dev site1dev
Expected output:
Creating home directory `/srv/clients/site1/dev' ...
Copying files from `/etc/skel' ...
Explanation: Places the user's workspace near the project tree. Use case: Isolated per-client management structure.
5. Create account with explicit shell
sudo adduser --shell /bin/bash wpeditor
Expected output:
Adding user `wpeditor' ...
Explanation: Sets login shell during creation instead of modifying later. Use case: Ensure expected shell for maintenance scripts.
6. Add existing user to web group
sudo usermod -aG www-data wpdev && groups wpdev
Expected output:
wpdev : wpdev www-data
Explanation: Grants supplementary group access to WordPress files.
Use case: Allow controlled edits inside /var/www/html.
7. Verify account details after creation
id wpdev && getent passwd wpdev
Expected output:
uid=1003(wpdev) gid=1003(wpdev) groups=1003(wpdev),33(www-data)
wpdev:x:1003:1003:,,,:/home/wpdev:/bin/bash
Explanation: Confirms UID/GID, groups, home, and shell. Use case: Post-onboarding validation checklist.
8. Bulk create temporary training users
for u in trainee1 trainee2 trainee3; do sudo adduser --disabled-password --gecos "Training User,,," "$u"; done
Expected output:
Adding user `trainee1' ...
Adding user `trainee2' ...
Adding user `trainee3' ...
Explanation: Creates multiple low-friction accounts consistently. Use case: Short-term workshop access on staging VPS.
Common Mistakes & Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| :-- | :-- | :-- |
Only root may add a user | Command run without privilege | Run sudo adduser USERNAME |
User cannot write in /var/www/html | User not in www-data group | Run sudo usermod -aG www-data USERNAME and re-login |
| Home directory not created where expected | Wrong or missing --home value | Recreate with sudo userdel -r USERNAME then sudo adduser --home DIR USERNAME |
| Account can still SSH after offboarding prep | Password disabled but SSH key still present | Remove key file: sudo rm -f /home/USERNAME/.ssh/authorized_keys |
| Wrong shell assigned | Default shell inherited from system config | Correct with sudo usermod -s /bin/bash USERNAME |
Best Practices
- Create one account per human: Never share admin credentials across team members.
- Use groups for access control: Grant
www-dataonly where web-write access is required. - Prefer key-based auth: Pair
--disabled-passwordwith managed SSH keys. - Validate immediately: Run
id,groups, andgetent passwdright after creation. - Offboard quickly: Disable or delete unused accounts to reduce attack surface.
Hands-On Practice
Task: Onboard a New WordPress Maintainer
- Create
siteopswithsudo adduser --disabled-password --gecos "Site Ops,,," siteops. - Grant web access using
sudo usermod -aG www-data siteops, then confirm withgroups siteops. - Challenge: Restrict the account to key-based access, add a managed key to
/home/siteops/.ssh/authorized_keys, and verify login plus write access to/var/www/html/wp-content.
Connection to Other Concepts
- groups: Verify whether your new account is in the correct supplementary groups.
- id: Confirm UID/GID mappings before setting file ownership.
- usermod: Adjust shell, expiry, and group membership after onboarding.
- userdel: Cleanly remove temporary or departed-user accounts.
Visual Learning Diagram
What's Next: Proceed to groups — Verify Group Membership to audit exactly what each user can access.